import { assert, describe, it, layer } from "@effect/vitest"
import { ChainRegistry } from "@unionlabs/sdk/ChainRegistry"
import * as Ucs03 from "@unionlabs/sdk/Ucs03"
import { Effect, pipe, Schema as S } from "effect"
import { toHex } from "viem"

// @ts-ignore
BigInt["prototype"].toJSON = function() {
  return this.toString()
}

describe("UCS03", () => {
  describe("Zkgm.t.sol", () => {
    /**
     * @see https://github.com/unionlabs/union/blob/69ee9d5/evm/tests/src/05-app/Zkgm.t.sol#L6202
     */
    it.effect("test_create_foa()", () =>
      Effect.gen(function*() {
        const order = Ucs03.TokenOrderV1.fromOperand([
          toHex("union1jk9psyhvgkrt2cumz8eytll2244m2nnz4yt2g2"),
          "0xBe68fC2d8249eb60bfCf0e71D5A0d2F2e292c4eD",
          "0x6d756e6f",
          100n,
          "muno",
          "muno",
          6,
          0n,
          "0x16628cB81ffDA9B8470e16299eFa5F76bF45A579",
          100n,
        ])
        assert.equal(
          (yield* S.encode(Ucs03.Ucs03WithInstructionFromHex)(order)).toLowerCase(),
          "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000002c756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a34797432673200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014be68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d756e6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d756e6f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d756e6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001416628cb81ffda9b8470e16299efa5f76bf45a579000000000000000000000000",
        )
      }))

    /**
     * @see https://github.com/unionlabs/union/blob/69ee9d5/evm/tests/src/05-app/Zkgm.t.sol#L6384
     */
    it.effect("test_create_foa_v2_image_cosmwasm()", () =>
      Effect.gen(function*() {
        const order = Ucs03.TokenOrderV2.fromOperand([
          "0xBe68fC2d8249eb60bfCf0e71D5A0d2F2e292c4eD",
          toHex("union1jk9psyhvgkrt2cumz8eytll2244m2nnz4yt2g2"),
          "0x49aCf968c7E8807B39e980b2a924E97C8ead3a22",
          10n,
          toHex("union1uyxeud073ttss4stt92hvt4wgzzyrssqata8058305km6xp7vzgs85kpst"),
          10n,
          1,
          "0xe8d01a88f46d02e2e857eaaf5c922699b5edc2dbd6eb4fa2049a472a0bb7a7db",
        ])
        const encoded = yield* S.encode(Ucs03.Ucs03FromHex)(order)
        assert.equal(
          encoded.toLowerCase(),
          "0x0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000014be68fc2d8249eb60bfcf0e71d5a0d2f2e292c4ed000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c756e696f6e316a6b397073796876676b72743263756d7a386579746c6c323234346d326e6e7a3479743267320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001449acf968c7e8807b39e980b2a924e97c8ead3a220000000000000000000000000000000000000000000000000000000000000000000000000000000000000040756e696f6e31757978657564303733747473733473747439326876743477677a7a7972737371617461383035383330356b6d36787037767a677338356b7073740000000000000000000000000000000000000000000000000000000000000020e8d01a88f46d02e2e857eaaf5c922699b5edc2dbd6eb4fa2049a472a0bb7a7db",
        )
      }))
  })

  it.effect("birth", () =>
    Effect.gen(function*() {
      assert.deepStrictEqual(
        yield* pipe(
          "0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000204b2c85a26bb9fb2400000000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000204b2c85a26bb9fb2400000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000002c756e696f6e316a6768663236753576777278666e6435376a78657a736e73687a637a777767796878776a706500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014d31e23d60e07fa632334c2a671733a068592c638000000000000000000000000000000000000000000000000000000000000000000000000000000000000000261750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014ba5ed44733953d79717f6269357c77718c8ba5ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014ba5ed44733953d79717f6269357c77718c8ba5ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" as const,
          S.decode(Ucs03.Ucs03WithInstructionFromHex),
        ),
        Ucs03.TokenOrderV2.make({
          opcode: 3,
          version: 2,
          operand: [
            "0x756e696f6e316a6768663236753576777278666e6435376a78657a736e73687a637a777767796878776a7065",
            "0xd31e23d60e07fa632334c2a671733a068592c638",
            "0x6175",
            9994400000000000000000000000n,
            "0xba5ed44733953d79717f6269357c77718c8ba5ed",
            9994400000000000000000000000n,
            3,
            "0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014ba5ed44733953d79717f6269357c77718c8ba5ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
          ],
        }),
      )
    }))
  it.effect.only("qlp", () =>
    Effect.gen(function*() {
      const result = yield* pipe(
        "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000007400000000000000000000000000000000000000000000000000000000000000a2000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000001406627714f3F17a701f7074a12C02847a5D2Ca487000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c756e696f6e3132326e79336d6570326c376e687461667077617632793965356a72736c68656b373668736a6c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014ba5eD44733953d79717F6269357C77718C8Ba5ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000002617500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014ba5ed44733953d79717f6269357c77718c8ba5ed000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001406627714f3F17a701f7074a12C02847a5D2Ca487000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c756e696f6e3132326e79336d6570326c376e687461667077617632793965356a72736c68656b373668736a6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001837b22636f6e7472616374223a2230783735366536393666366533313635373536353735363537353635373533393736363137323334373936383634373237353739376136623661363337333638333733343738376136353735363733363633366237393739333633303638373333303736363337313665376137313663333236383731333036633738363333323636222c226d7367223a2265794a746157353058335276496a6f694d4867334e545a6c4e6a6b325a6a5a6c4d7a457a4d6a4d794e6d55334f544d7a4e6d51324e5463774d7a4932597a4d334e6d55324f4463304e6a45324e6a63774e7a63324d5463324d7a49334f544d354e6a557a4e545a684e7a49334d7a5a6a4e6a67324e545a694d7a637a4e6a59344e7a4d3259545a6a4969776962576c7558323170626e52665957317664573530496a6f694d534a39222c2266756e6473223a5b7b2264656e6f6d223a226175222c22616d6f756e74223a2231227d5d2c2263616c6c5f616374696f6e223a2263616c6c5f70726f7879227d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001406627714f3F17a701f7074a12C02847a5D2Ca487000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c756e696f6e3132326e79336d6570326c376e687461667077617632793965356a72736c68656b373668736a6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001187b22636f6e7472616374223a2230783735366536393666366533313635373536353735363537353635373533393736363137323334373936383634373237353739376136623661363337333638333733343738376136353735363733363633366237393739333633303638373333303736363337313665376137313663333236383731333036633738363333323636222c226d7367223a2265794a7a634756755a475679496a6f694d4867315a6d4a6c4e7a52684d6a677a5a6a63354e54526d4d54426859544130597a4a6c5a4759314e5455334f4467784d57466c596a417a496977695957317664573530496a6f694d534a39222c2266756e6473223a5b5d2c2263616c6c5f616374696f6e223a22646972656374227d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001406627714f3F17a701f7074a12C02847a5D2Ca487000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c756e696f6e3132326e79336d6570326c376e687461667077617632793965356a72736c68656b373668736a6c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017c7b22636f6e7472616374223a22307835666265373461323833663739353466313061613034633265646635353537383831316165623033222c226d7367223a2265794a66615751694f694a465a6d5a6c593351694c434a66623341694f694a50626c4e3159324e6c63334d694c434a6c5a6d5a6c593352666157357a64484a315933527062323566615441694f6e736958326c6b496a6f6952575a6d5a574e304969776958323977496a6f695432355464574e6a5a584e7a496977695a575a6d5a574e3058326c756333527964574e306157397558326b77496a7037496c39705a434936496b566d5a6d566a64434973496c397663434936496b39755533566a5932567a63794973496d566d5a6d566a64463970626e4e30636e566a64476c76626c39704d43493665794a66615751694f694a465a6d5a6c593351694c434a66623341694f694a4462323174615851696658313966513d3d222c2266756e6473223a5b5d2c2263616c6c5f616374696f6e223a22646972656374227d00000000" as const,
        S.decode(Ucs03.Ucs03FromHex),
      )

      console.log({ result: JSON.stringify(result, null, 2) })
    }))

  describe.only("Call", () => {
    it.effect("decodes from packet", () =>
      Effect.gen(function*() {
        const packetData =
          "0x79176e1d5f2779e14b2f5f885bfe7b35e78802643522ce0dad5cac4e4a44271f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002e00000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000000001415ee7c367f4232241028c36e720803100757c6e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e62626e316d377a72356a77346b397a32327239616a676766347563616c7779377578767539676b7736746e736d7634326c766a706b7761736167656b356700000000000000000000000000000000000000000000000000000000000000000014e53dcec07d16d88e386ae0710e86d9a400f83c31000000000000000000000000000000000000000000000000000000000000000000000000000000000000000442414259000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007426162796c6f6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047562626e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001415ee7c367f4232241028c36e720803100757c6e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e62626e316d377a72356a77346b397a32327239616a676766347563616c7779377578767539676b7736746e736d7634326c766a706b7761736167656b3567000000000000000000000000000000000000000000000000000000000000000000b27b22626f6e64223a7b22616d6f756e74223a223130303030222c2273616c74223a22307833313333303831396135613232336439376163373134663239616535653361646265396565663833383233373830663761393063636536363461626138366565222c226578706563746564223a2239373237222c22726563697069656e74223a2262626e3168637533306461647770686638397533783375366a327a35387233376339616b687866637330227d7d0000000000000000000000000000" as const

        const decoded = yield* S.decode(Ucs03.PacketFromHex)(packetData)
        const ucs03 = yield* S.decode(Ucs03.Ucs03FromInstruction)(decoded.instruction)

        console.log({ decoded })

        console.log(JSON.stringify(ucs03, null, 2))
      }))

    layer(ChainRegistry.Default)(
      "ChainRegistry.Default",
      (it) => {
        it.effect("with real chain data", () =>
          Effect.gen(function*() {
            // const registry = yield* ChainRegistry
            // const source = yield* registry.byUniversalId(
            //   UniversalChainId.make("ethereum.1"),
            // )
            // const destination = yield* registry.byUniversalId(
            //   UniversalChainId.make("babylon.bbn-1"),
            // )
            // const sender = Ucs05.EvmDisplay.make({
            //   address: "0x15ee7c367f4232241028c36e720803100757c6e9",
            // })
            // const receiver = Ucs05.CosmosDisplay.make({
            //   address: "bbn1m7zr5jw4k9z22r9ajggf4ucalwy7uxvu9gkw6tnsmv42lvjpkwasagek5g",
            // })
            // const call = Call.make({
            //   sender,
            //   eureka: false,
            //   contractAddress: receiver,
            //   contractCalldata:
            //     "0x7b22626f6e64223a7b22616d6f756e74223a223130303030222c2273616c74223a22307833313333303831396135613232336439376163373134663239616535653361646265396565663833383233373830663761393063636536363461626138366565222c226578706563746564223a2239373237222c22726563697069656e74223a2262626e3168637533306461647770686638397533783375366a327a35387233376339616b687866637330227d7d" as const,
            // })

            // const order = yield* TokenOrder.make({
            //   source,
            //   destination,
            //   sender,
            //   receiver,
            //   baseToken: Token.Erc20.make({
            //     address: "0xe53dcec07d16d88e386ae0710e86d9a400f83c31",
            //   }),
            //   baseAmount: 10000n,
            //   kind: "escrow",
            //   quoteToken: Token.CosmosBank.make({ address: "ubbn" }),
            //   quoteAmount: 10000n,
            //   version: 1,
            //   metadata: undefined,
            // })

            // const batch = Batch.make([order, call])

            // console.log(JSON.stringify(batch, null, 2))
          }))
      },
    )
  })
})
